home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1997 January: Mac OS SDK / Dev.CD Jan 97 SDK2.toast / Development Kits (Disc 2) / OpenDoc Development Framework / ODFDev / ODF / Framewrk / FWPart / FWClpCmd.cpp < prev    next >
Encoding:
Text File  |  1996-09-17  |  14.4 KB  |  531 lines  |  [TEXT/MPS ]

  1. //========================================================================================
  2. //
  3. //    File:                FWClpCmd.cpp
  4. //    Release Version:    $ ODF 2 $
  5. //
  6. //    Copyright:            (c) 1993 - 1996 by Apple Computer, Inc., all rights reserved.
  7. //
  8. //========================================================================================
  9.  
  10. #include "FWFrameW.hpp"
  11.  
  12. #ifndef FWCLPCMD_H
  13. #include "FWClpCmd.h"
  14. #endif
  15.  
  16. #ifndef FWPART_H
  17. #include "FWPart.h"
  18. #endif
  19.  
  20. #ifndef FWINTER_H
  21. #include "FWInter.h"
  22. #endif
  23.  
  24. #ifndef FWFRAME_H
  25. #include "FWFrame.h"
  26. #endif
  27.  
  28. #ifndef FWPRESEN_H
  29. #include "FWPresen.h"
  30. #endif
  31.  
  32. #ifndef FWSELECT_H
  33. #include "FWSelect.h"
  34. #endif
  35.  
  36. #ifndef FWLINK_H
  37. #include "FWLink.h"
  38. #endif
  39.  
  40. #ifndef FWLNKMGR_H
  41. #include "FWLnkMgr.h"
  42. #endif
  43.  
  44. #ifndef FWSESION_H
  45. #include "FWSesion.h"
  46. #endif
  47.  
  48. // ----- OS Layer -----
  49.  
  50. #ifndef FWBARRAY_H
  51. #include "FWBArray.h"
  52. #endif
  53.  
  54. #ifndef SLODFSTR_K
  55. #include "SLODFStr.k"
  56. #endif
  57.  
  58. #ifndef SLODFSTR_H
  59. #include "SLODFStr.h"
  60. #endif
  61.  
  62. // ----- OpenDoc Includes -----
  63.  
  64. #ifndef SOM_Module_OpenDoc_Commands_defined
  65. #include <CmdDefs.xh>
  66. #endif
  67.  
  68. #ifndef SOM_ODClipboard_xh
  69. #include <Clipbd.xh>
  70. #endif
  71.  
  72. #ifndef SOM_Module_OpenDoc_StdProps_defined
  73. #include <StdProps.xh>
  74. #endif
  75.  
  76. #ifndef SOM_Module_OpenDoc_StdTypes_defined
  77. #include <StdTypes.xh>
  78. #endif
  79.  
  80. #ifndef SOM_ODStorageUnit_xh
  81. #include <StorageU.xh>
  82. #endif
  83.  
  84. #ifndef SOM_ODLinkSpec_xh
  85. #include <LinkSpec.xh>
  86. #endif
  87.  
  88. //========================================================================================
  89. //    Runtime Info
  90. //========================================================================================
  91.  
  92. #ifdef FW_BUILD_MAC
  93. #pragma segment odfcommands
  94. #endif
  95.  
  96. FW_DEFINE_AUTO(FW_CClipboardCommand)
  97.  
  98. //========================================================================================
  99. // FW_CClipboardCommand class
  100. //========================================================================================
  101.  
  102. //----------------------------------------------------------------------------------------
  103. // FW_CClipboardCommand constructor
  104. //----------------------------------------------------------------------------------------
  105.  
  106. FW_CClipboardCommand::FW_CClipboardCommand(Environment* ev,
  107.                                 ODCommandID id,
  108.                                 FW_CFrame* frame, 
  109.                                 FW_Boolean canUndo) 
  110. :    FW_CCommand(ev, id, frame, id == kODCommandCopy ? FALSE :canUndo),
  111.     fUpdateID(kODUnknownUpdate),
  112.     fCloneKind(kODCloneCopy),
  113.     fPasteAsHandler(NULL),
  114.     fSelection(NULL)
  115. {
  116.     short undoMsgID;
  117.     
  118.     switch (id)
  119.     {
  120.         case kODCommandCopy:
  121.             SetCausesChange(ev, FALSE);        // Copy doesn't change the data
  122.             break;
  123.             
  124.         case kODCommandCut:
  125.             fCloneKind = kODCloneCut;
  126.             undoMsgID = FW_kUndoCutMsg;
  127.             break;
  128.             
  129.         case kODCommandPaste:
  130.             fCloneKind = kODClonePaste;
  131.             undoMsgID = FW_kUndoPasteMsg;
  132.             break;
  133.             
  134.         case kODCommandPasteAs:
  135.             fCloneKind = kODClonePaste;
  136.             undoMsgID = FW_kUndoPasteAsMsg;
  137.             break;
  138.             
  139.         case kODCommandClear:
  140.             undoMsgID = FW_kUndoClearMsg;
  141.             break;
  142.         
  143.         default:
  144.             undoMsgID = FW_kDefaultUndoMsg;
  145.             break;
  146.     }
  147.  
  148.     fSelection = frame->GetPresentation(ev)->GetSelection(ev);
  149.     
  150.     if (GetCanUndo(ev))
  151.     {
  152.         FW_CString undoString;
  153.         FW_CString redoString;
  154.         
  155.         ::FW_PrivLoadUndoStrings(ev, undoMsgID, undoString, redoString);
  156.         SetMenuStrings(ev, undoString, redoString);
  157.     }
  158.     FW_END_CONSTRUCTOR
  159. }
  160.  
  161. //----------------------------------------------------------------------------------------
  162. // FW_CClipboardCommand destructor
  163. //----------------------------------------------------------------------------------------
  164.  
  165. FW_CClipboardCommand::~FW_CClipboardCommand()
  166. {
  167.     FW_START_DESTRUCTOR
  168.     delete fPasteAsHandler;
  169. }
  170.  
  171. //----------------------------------------------------------------------------------------
  172. // FW_CClipboardCommand::DoIt
  173. //----------------------------------------------------------------------------------------
  174.  
  175. void FW_CClipboardCommand::DoIt(Environment* ev)    // Override
  176. {
  177.     FW_Boolean canDo = this->IsOKtoEdit(ev);
  178.  
  179.     if (canDo)
  180.     {
  181.         if (GetCanUndo(ev))
  182.             this->SaveUndoState(ev);    // save current state, for later Undo
  183.     
  184.         switch (GetCommandID(ev))
  185.         {
  186.             case kODCommandCopy:
  187.                 this->Copy(ev);
  188.                 break;
  189.     
  190.             case kODCommandClear:
  191.                 this->Clear(ev);
  192.                 break;
  193.     
  194.             case kODCommandCut:
  195.                 this->Cut(ev);
  196.                 break;
  197.     
  198.             case kODCommandPaste:
  199.                 canDo = this->Paste(ev);
  200.                 break;
  201.     
  202.             case kODCommandPasteAs:
  203.                 canDo = this->PasteAs(ev);
  204.                 break;
  205.         }
  206.     }
  207.     
  208.     if (canDo == FALSE)
  209.     {
  210.         SetCanUndo(ev, FALSE);
  211.         SetCausesChange(ev, FALSE);
  212.     }
  213.     else if (GetCanUndo(ev))
  214.     {
  215.         this->SaveRedoState(ev);        // save new state, for later Redo
  216.     }
  217. }
  218.  
  219.  
  220. //----------------------------------------------------------------------------------------
  221. //    FW_CClipboardCommand::Cut
  222. //----------------------------------------------------------------------------------------
  223.  
  224. void FW_CClipboardCommand::Cut(Environment* ev)
  225. {
  226.     PreCommand(ev);
  227.     
  228.     this->PrivCopy(ev, false);    // don't write a link spec for a cut
  229.     fSelection->ClearSelection(ev);
  230.     
  231.     // Give the command subclass a chance to do something
  232.     this->CommandDone(ev);
  233. }
  234.  
  235. //----------------------------------------------------------------------------------------
  236. //    FW_CClipboardCommand::Copy
  237. //----------------------------------------------------------------------------------------
  238.  
  239. void FW_CClipboardCommand::Copy(Environment* ev)
  240. {
  241.     PreCommand(ev);
  242.     
  243.     FW_Boolean allowLinking = (fSelection && fSelection->IsSelectionLinkable(ev));
  244.     this->PrivCopy(ev, allowLinking);
  245.     
  246.     CommandDone(ev);
  247. }
  248.  
  249. //----------------------------------------------------------------------------------------
  250. //    FW_CClipboardCommand::Clear
  251. //----------------------------------------------------------------------------------------
  252.  
  253. void FW_CClipboardCommand::Clear(Environment* ev)
  254. {
  255.     PreCommand(ev);
  256.     fSelection->ClearSelection(ev);
  257.     CommandDone(ev);    // Give the command subclass a chance to do something
  258. }
  259.  
  260. //----------------------------------------------------------------------------------------
  261. //    FW_CClipboardCommand::Paste
  262. //----------------------------------------------------------------------------------------
  263.  
  264. FW_Boolean FW_CClipboardCommand::Paste(Environment* ev)
  265. {
  266.     PreCommand(ev);
  267.     return PrivPaste(ev);    // will call CommandDone
  268. }
  269.  
  270. //----------------------------------------------------------------------------------------
  271. //    FW_CClipboardCommand::PrivPaste
  272. //----------------------------------------------------------------------------------------
  273.  
  274. FW_Boolean FW_CClipboardCommand::PrivPaste(Environment* ev)
  275. {
  276.     FW_Boolean result = FALSE;
  277.     
  278.     ODStorageUnit* clipBSU = FW_CSession::GetClipboard(ev)->GetContentStorageUnit(ev);
  279.  
  280.     result = GetPart(ev)->GetDataInterchange(ev)->InternalizeData(ev, fSelection->GetSelectedContent(ev), GetFrame(ev), clipBSU, FW_kClipboardStorage, fCloneKind, NULL) != FW_kInternalizeFailed;
  281.  
  282.     if (result)    
  283.     {
  284.         // notify OpenDoc clipboard
  285.         fUpdateID = FW_CSession::GetClipboard(ev)->ActionDone(ev, fCloneKind);
  286.  
  287.         // Give the command subclass a chance to do something
  288.         CommandDone(ev);
  289.     }
  290.  
  291.     return result;
  292. }
  293.  
  294. //----------------------------------------------------------------------------------------
  295. //    FW_CClipboardCommand::PasteAs
  296. //----------------------------------------------------------------------------------------
  297.  
  298. FW_Boolean FW_CClipboardCommand::PasteAs(Environment* ev)
  299. {
  300.     FW_Boolean result = false;
  301.     FW_VOLATILE(result);
  302.     FW_Boolean handledIt = false;
  303.  
  304.     PreCommand(ev);
  305.  
  306.     FW_TRY
  307.     {
  308.         // Create a PasteAs handler object to do some of the work
  309.         fPasteAsHandler = new FW_MPasteAsHandler(ev, GetFrame(ev));
  310.         result = fPasteAsHandler->HandlePasteAsDialog(ev, fCloneKind, handledIt);
  311.         if (!handledIt)
  312.         {
  313.             SetCommandID(ev, kODCommandPaste);
  314.             result = this->PrivPaste(ev);        // just an ordinary paste
  315.         }
  316.         else if (result)
  317.         {
  318.             // notify OpenDoc clipboard
  319.             fUpdateID = FW_CSession::GetClipboard(ev)->ActionDone(ev, fCloneKind);
  320.     
  321.             // if a link was created and established, need to post an End transaction
  322.             if (this->PrivWasLinkEstablished(ev))
  323.             {
  324.                 SetActionType(ev, kODEndAction);
  325.             }
  326.  
  327.             // Give the command subclass a chance to do something
  328.             this->CommandDone(ev);
  329.         }
  330.     }
  331.     FW_CATCH_BEGIN
  332.     FW_CATCH_EVERYTHING()
  333.     {
  334.         result = false;    // don't re-throw, just return false
  335.     }
  336.     FW_CATCH_END
  337.  
  338.     if (result == false || GetCommandID(ev) == kODCommandPaste)
  339.     {
  340.         // PasteAs handler either not used or not needed
  341.         delete fPasteAsHandler;
  342.         fPasteAsHandler = NULL;
  343.     }
  344.     
  345.     return result;
  346. }
  347.  
  348. //----------------------------------------------------------------------------------------
  349. //    FW_CClipboardCommand::PrivCopy
  350. //----------------------------------------------------------------------------------------
  351.  
  352. void FW_CClipboardCommand::PrivCopy(Environment* ev, FW_Boolean allowLinking)
  353. {
  354.     ODClipboard* clipboard = FW_CSession::GetClipboard(ev);
  355.     
  356.     //---- We have to invalidate any currently pending link ----
  357.     FW_CLinkManager* linkMgr = GetPart(ev)->GetLinkManager(ev);
  358.     if (linkMgr)
  359.         linkMgr->DeletePendingClipboardLink(ev);
  360.  
  361.     //---- Clear any leftover promises on the clipboard ----
  362.     clipboard->GetContentStorageUnit(ev)->ClearAllPromises(ev);
  363.     GetPart(ev)->GetDataInterchange(ev)->PrivDeletePromises(ev, FW_kClipboardStorage);
  364.  
  365.     //---- Clear all properties and values from the clipboard ----
  366.     clipboard->Clear(ev);
  367.     
  368.     // [HLX] Getting the clipboardSU before calling clipboard->Clear(ev) results in 
  369.     // a crash in ExternalizeData when I try to get the draft?????
  370.     ODStorageUnit* clipboardSU = clipboard->GetContentStorageUnit(ev);
  371.     
  372.     //---- Write new data to the clipboard ----
  373.     GetPart(ev)->GetDataInterchange(ev)->ExternalizeData(ev, 
  374.                                                     fSelection->GetSelectedContent(ev), 
  375.                                                     GetFrame(ev), 
  376.                                                     clipboardSU, 
  377.                                                     FW_kClipboardStorage, 
  378.                                                     fCloneKind);
  379.  
  380.     //---- notify OpenDoc clipboard ----
  381.     fUpdateID = clipboard->ActionDone(ev, fCloneKind);
  382.  
  383.     // ---- Save clipboard update id ----            
  384.     GetPart(ev)->GetDataInterchange(ev)->PrivSetClipboardUpdateID(ev, fUpdateID);
  385.  
  386.     // ----- Write out Link Spec if possible -----
  387.     if (allowLinking)
  388.     {
  389.         ODLinkSpec* linkSpec = NULL;
  390.         FW_VOLATILE(linkSpec);
  391.         ODUpdateID updateID = fUpdateID;
  392.         FW_CByteArray data(&updateID, sizeof(ODUpdateID));
  393.  
  394.         FW_TRY
  395.         {
  396.             linkSpec = GetPart(ev)->GetDraft(ev)->CreateLinkSpec(ev, GetPart(ev)->GetODPart(ev), data);
  397.  
  398.             clipboardSU->AddProperty(ev, kODPropLinkSpec);
  399.             linkSpec->WriteLinkSpec(ev, clipboardSU);
  400.         }
  401.         FW_CATCH_BEGIN
  402.         FW_CATCH_EVERYTHING()
  403.         {
  404.             if (linkSpec)
  405.                 delete linkSpec;
  406.             FW_THROW_SAME();
  407.         }
  408.         FW_CATCH_END
  409.  
  410.         delete linkSpec;
  411.  
  412.         // If current selection is already published, just re-use its link
  413.         FW_CLinkSource* linkSource = fSelection->DoFindLinkSource(ev);
  414.         if (linkSource)
  415.             linkSource->SetPendingID(ev, updateID);
  416.         else
  417.             linkSource = linkMgr->NewLinkSource(ev, updateID, GetPresentation(ev));
  418.         linkMgr->SetPendingClipboardLink(ev, linkSource);
  419.     }
  420. }
  421.  
  422. //----------------------------------------------------------------------------------------
  423. //    FW_CClipboardCommand::UndoIt
  424. //----------------------------------------------------------------------------------------
  425.  
  426. void FW_CClipboardCommand::UndoIt(Environment* ev)    // Override
  427. {
  428.     switch (GetCommandID(ev))
  429.     {
  430.         case kODCommandCut:
  431.         case kODCommandPaste:
  432.         case kODCommandPasteAs:
  433.         {
  434.             FW_CSession::GetClipboard(ev)->ActionUndone(ev, fUpdateID, fCloneKind);
  435.         }
  436.     }
  437. }
  438.  
  439. //----------------------------------------------------------------------------------------
  440. //    FW_CClipboardCommand::RedoIt
  441. //----------------------------------------------------------------------------------------
  442.  
  443. void FW_CClipboardCommand::RedoIt(Environment* ev)    // Override
  444. {
  445.     switch (GetCommandID(ev))
  446.     {
  447.         case kODCommandCut:
  448.         case kODCommandPaste:
  449.         case kODCommandPasteAs:
  450.         {
  451.             FW_CSession::GetClipboard(ev)->ActionRedone(ev, fUpdateID, fCloneKind);
  452.         }
  453.     }
  454. }
  455.  
  456. //----------------------------------------------------------------------------------------
  457. //    FW_CClipboardCommand::PreCommand
  458. //----------------------------------------------------------------------------------------
  459.  
  460. void FW_CClipboardCommand::PreCommand(Environment* ev)
  461. {
  462. FW_UNUSED(ev);
  463.     // User may override; gets called before the command's function is done
  464. }
  465.  
  466. //----------------------------------------------------------------------------------------
  467. //    FW_CClipboardCommand::CommandDone
  468. //----------------------------------------------------------------------------------------
  469.  
  470. void FW_CClipboardCommand::CommandDone(Environment* ev)
  471. {
  472. FW_UNUSED(ev);
  473.     // User may override; only gets called if the command was successful
  474. }
  475.  
  476. //----------------------------------------------------------------------------------------
  477. //    FW_CClipboardCommand::IsOKtoEdit
  478. //----------------------------------------------------------------------------------------
  479.  
  480. FW_Boolean FW_CClipboardCommand::IsOKtoEdit(Environment* ev)
  481. {
  482.  
  483.     // This used to call fSelection::CanEditSelection, but that's not appropriate for
  484.     // all clipboard actions.  In fact, with the current set of sample parts, it's 
  485.     // not appropriate for any clipboard actions.  If the command architecture remains
  486.     // more or less as it is, then this implementation will probably be removed.  Part's
  487.     // will implement any necessary additional testing in their overrides of this method.
  488.     
  489.     FW_Boolean result = FW_CCommand::IsOKtoEdit(ev);
  490.     return result;
  491. }
  492.  
  493. //----------------------------------------------------------------------------------------
  494. //    FW_CClipboardCommand::GetNewLink
  495. //----------------------------------------------------------------------------------------
  496.  
  497. FW_CLinkDestination* FW_CClipboardCommand::GetNewLink(Environment* ev) const
  498. {
  499.     return fPasteAsHandler ? fPasteAsHandler->GetNewLink(ev) : NULL;
  500. }
  501.  
  502. //----------------------------------------------------------------------------------------
  503. //    FW_CClipboardCommand::PrivWasLinkEstablished
  504. //----------------------------------------------------------------------------------------
  505. FW_Boolean FW_CClipboardCommand::PrivWasLinkEstablished(Environment* ev)
  506. {
  507.     FW_CLinkDestination* newLink = this->GetNewLink(ev);
  508.     if (newLink == NULL)
  509.         return false;
  510.  
  511.     // Link was created, but has it been established?
  512.     FW_Boolean result = newLink->IsEstablished(ev);
  513.  
  514.     // If link was created but not established, defer posting an End action
  515.     if (result == false)
  516.     {
  517.         newLink->PrivSetCommandToEndAction(ev, this);
  518.         // When the link is finally established the command will post an End action.
  519.     }
  520.  
  521.     return result;
  522. }
  523.  
  524. //----------------------------------------------------------------------------------------
  525. // FW_CClipboardCommand::PrivAddEndAction
  526. //----------------------------------------------------------------------------------------
  527. void FW_CClipboardCommand::PrivAddEndAction(Environment* ev) 
  528. {
  529.     AddAction(ev, kODEndAction, NULL, 0, GetUndoString(ev), GetRedoString(ev));
  530. }
  531.